package com.cxs.studentManagerSystem.utils;

import lombok.extern.slf4j.Slf4j;

import javax.servlet.http.HttpServletRequest;
import java.beans.PropertyDescriptor;
import java.lang.reflect.Field;
import java.lang.reflect.ParameterizedType;
import java.lang.reflect.Type;
import java.sql.Timestamp;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Date;
import java.util.List;
import java.util.Map;

/**
 * @Project: wanju-web
 * @Author: cxs2014501@163.com
 * @Create: 2022/9/14 15:56
 * @Description:
 **/
@Slf4j
public class BeanUtils {

    public static final String DATA_FORMAT = "yyyy-MM-dd HH:mm:ss";

    /**
     * 对象属性copy
     * @param origin 源object
     * @param target 目标object
     */
    public static void copyOfProperties(Object origin, Object target){
        if (null == origin || null == target) {
            return;
        }
        Class<?> originClazz = origin.getClass();
        Class<?> targetClazz = target.getClass();
        Field[] fields = targetClazz.getDeclaredFields();
        if (null != fields && fields.length > 0) {
            for (Field field : fields) {
                field.setAccessible(true);
                try {
                    PropertyDescriptor pd = new PropertyDescriptor(field.getName(), originClazz);
                    field.set(target, pd.getReadMethod().invoke(origin));
                } catch (Exception e) {
                    log.error("对象属性copy出错, {}", e.getMessage());
                    continue;
                }
            }
        }
    }

    /**
     * 请求参数封装
     * @param request
     * @param clazz 目标Bean.class
     * @param rebackFlag 是否数据回显，默认false
     * @param <T>
     * @return
     */
    public static <T> T requestParamAsBean(HttpServletRequest request, Class<T> clazz, Boolean rebackFlag){
        T result = null;
        try {
            result = clazz.newInstance();;
            if (clazz == null) {
                return result;
            }
            if (rebackFlag == null) {
                rebackFlag = Boolean.FALSE;
            }
            Map<String, String[]> parameterMap = request.getParameterMap();
            if (null != parameterMap && parameterMap.size() > 0) {
                for (Map.Entry<String, String[]> entry: parameterMap.entrySet()) {
                    String key = entry.getKey();
                    String[] values = entry.getValue();
                    if (rebackFlag) {
                        request.setAttribute(key, values[0]);
                    }
                    Field field = null;
                    try {
                        field = clazz.getDeclaredField(key);
                        field.setAccessible(true);
                    } catch (Exception e) {
                        continue;
                    }
                    if (field == null) {
                        continue;
                    }
                    Class<?> propertyType = field.getType();
                    if (propertyType.equals(Integer.class)) {
                        field.set(result, Integer.parseInt(values[0]));
                    } else if(propertyType.equals(Long.class)){
                        field.set(result, Long.parseLong(values[0]));
                    } else if(propertyType.equals(Double.class)){
                        field.set(result, Double.valueOf(values[0]));
                    } else if(propertyType.equals(Date.class)){
                        SimpleDateFormat dateFormat = new SimpleDateFormat(DATA_FORMAT);
                        field.set(result, dateFormat.parse(values[0]));
                    } else if(propertyType.equals(LocalDate.class)){
                        DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd");
                        field.set(result, LocalDate.parse(values[0], formatter));
                    } else if(propertyType.equals(LocalDateTime.class)){
                        DateTimeFormatter formatter = DateTimeFormatter.ofPattern(DATA_FORMAT);
                        field.set(result, LocalDateTime.parse(values[0], formatter));
                    } else if(propertyType.equals(Timestamp.class)){
                        SimpleDateFormat dateFormat = new SimpleDateFormat(DATA_FORMAT);
                        field.set(result, new Timestamp(dateFormat.parse(values[0]).getTime()));
                    } else if(propertyType.equals(Double.class)){
                        field.set(result, Double.valueOf(values[0]));
                    } else if(propertyType.equals(Float.class)){
                        field.set(result, Float.valueOf(values[0]));
                    } else if(propertyType.equals(String.class)){
                        field.set(result, values[0]);
                    } else if(propertyType.equals(List.class)){
                        Type genericType = field.getGenericType();
                        if (genericType != null && genericType instanceof ParameterizedType) {
                            ParameterizedType type = (ParameterizedType) genericType;
                            Type[] actualTypeArguments = type.getActualTypeArguments();
                            // 只处理一个泛型的
                            if (actualTypeArguments != null && actualTypeArguments.length == 1) {
                                Class typeClass = (Class) actualTypeArguments[0];
                                if (typeClass.equals(Integer.class)) {
                                    List<Integer> intList = new ArrayList<>();
                                    for (String value : values) {
                                        try {
                                            intList.add(Integer.parseInt(value));
                                        } catch (NumberFormatException e) {
                                            e.printStackTrace();
                                        }
                                    }
                                    field.set(result, intList);
                                } else if (typeClass.equals(String.class)){
                                    field.set(result, Arrays.asList(values));
                                }
                            }
                        }
                    }
                }
            }
        } catch (InstantiationException e) {
            e.printStackTrace();
        } catch (IllegalAccessException e) {
            e.printStackTrace();
        } catch (ParseException e) {
            e.printStackTrace();
        }
        return result;
    }
}
